package com.gt.facebook;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.Facebook.DialogListener;
import com.facebook.android.FacebookError;
import com.facebook.android.FbDialog;
import com.facebook.android.R;
import com.gt.facebook.pojo.Friend;

/**
 * 
 * This is the manager of Facebook. Contains login, logout, update user information.etc.
 * It will send broadcast to notify the status of Facebook.
 * The name of broadcast can be fetched with the field BROADCAST_ACTION.
 * 
 * @author Jigar
 *
 */
public class FacebookManager {

	private static final String TAG="FacebookManager";
	
	/*
	 * This ID should be fetched from facebook website. 
	 * There is a unique ID for every app.
	 * Change this to your own app ID.
	 */
	private static final String APP_ID="253711894731082";
	
	String[] PERMISSIONS = { "publish_stream","read_stream","offline_access",
			"user_photos", "publish_checkins", "photo_upload" };
	
	private static FacebookManager instance;
	private Context mContext;
	
	public static final String BROADCAST_ACTION="com.gt.facebook.FacebookManager";
	public static final String BROADCAST_EXTRA_NAME="BROADCAST_EXTRA_NAME";
	
	private Handler handler=null;
	//{ handler message.
	/**
	 * 表示login开始。收到该MSG后，不需要显示loading.因为已经有。
	 */
	public static final int MSG_LOGIN_BEGIN=201;
	
	/**
	 * 用户在login界面上按取消键。
	 */
	public static final int MSG_LOGIN_CANCEL=202;
	
	/**
	 * login过程中出错。出错信息可以从getLastLoginErrorMessage()获得。
	 */
	public static final int MSG_LOGIN_ERROR=203;
	
	/**
	 * 表示login结束，不管是成功，失败，出错还是取消。
	 * 
	 */
	public static final int MSG_LOGIN_END=204;
	
	public static final int MSG_LOGIN_TIMEOUT=205;
	
	/**
	 * 收到该MSG后，可以显示loading.
	 */
	public static final int MSG_LOGOUT_BEGIN=401;
	
	/**
	 * 收到该MSG后，可以取消loading.
	 */
	public static final int MSG_LOGOUT_END=404;
	
	public static final int MSG_LOGOUT_IO_ERROR=407;
	
	/**
	 * 开始获取用户资料。
	 */
	public static final int MSG_REQUEST_USER_BEGIN=501;
	public static final int MSG_REQUEST_USER_END=504;
	public static final int MSG_REQUEST_USER_LOST=509;
	public static final int MSG_REQUEST_USER_STATUS_BEGIN = 510;
	public static final int MSG_REQUEST_USER_STATUS_END = 511;
	public static final int MSG_REQUEST_USER_STATUS_ERROR = 512;
	public static final int MSG_REQUEST_USER_FRIENDS_BEGIN = 520;
	public static final int MSG_REQUEST_USER_FRIENDS_END = 521;
	public static final int MSG_REQUEST_USER_FRIENDS_ERROR = 522;
	
	public static final int MSG_SHARE_PHOTO_CANCEL=601;
	public static final int MSG_SHARE_PHOTO_FB_ERROR=602;
	public static final int MSG_SHARE_PHOTO_IO_ERROR=603;
	public static final int MSG_SHARE_PHOTO_END=604;
	public static final int MSG_SHARE_PHOTO_TIMEOUT=605;
	
	public static final int MSG_SHARE_LINK_CANCEL=701;
	public static final int MSG_SHARE_LINK_FB_ERROR=702;
	public static final int MSG_SHARE_LINK_ERROR=703;
	public static final int MSG_SHARE_LINK_END=704;
	public static final int MSG_SHARE_LINK_TIMEOUT=705;
	
	public static final int MSG_POST_LINK_FB_ERROR=802;
	public static final int MSG_POST_LINK_IO_ERROR=803;
	public static final int MSG_POST_LINK_END=804;
	
	public static final int MSG_SHARE_ACTION_FB_ERROR=902;
	public static final int MSG_SHARE_ACTION_IO_ERROR=903;
	public static final int MSG_SHARE_ACTION_END=904;

	public static final int MSG_SHARE_ACTION_CANCEL=901;
	public static final int MSG_SHARE_ACTION_TIMEOUT=905;
	public static final int MSG_SHARE_ACTION_ERROR=909;
	
	public static final int MSG_PROGRESS_DIALOG_ON_CANCLEL = 101;
	//}
	
	private boolean requestUserData=false;
	
	/**
	 * The user's Facebook ID
	 * 作为上传图片的参数之一,可以在requestUserData()的回调函数中获得。
	 */
	private String userId=null;
	
	/**
	 * The user's full name
	 */
	private String username=null;
	private String lastLoginErrorMessage=null;
	
	private Facebook mFacebook=null;
	private AsyncFacebookRunner mAsyncRunner=null;
	
	
	/**
	 * The user's status
	 */
	private String userStatus = null;
	
	/**
	 * The user's friend list. (need call requestUserFriends() to get data.)
	 */
	private List<Friend> mFriendList = new ArrayList<Friend>();
	
//	private static final String ACTION_FEED="feed";
	
	//{persistent
	private static final String SHAREPREF_NAME="SHAREPREF_NAME_facebook";
	private static final String KEY_ACCESS_TOKEN="KEY_ACCESS_TOKEN";
	private static final String KEY_ACCESS_EXPIRES="KEY_ACCESS_EXPIRES";
	private static final String KEY_USERNAME="KEY_USERNAME";
	private static final String KEY_USERID="KEY_USERID";
	private static final String KEY_USER_STATUS = "KEY_USER_STATUS";
	//}
	
	private int countRequestUserData=0;
	private static final int LIMIT_RETRY_USER_DATA=10;
	private static int resIdTextNoUserInfo=0;
	private static int resIdButtonOk=R.string.button_ok;
	
	private static int resIdOfflineDialogTitle=R.string.offline_dialog_title;
	private static int resIdOfflineDialogMessage=R.string.offline_dialog_message;
	
	//
	private boolean isCheckNetwork=false;
	private boolean isUseCustomProgressDialog=false;
	
	private FacebookManager(Context context,String appId){
		this.mContext=context;
		
		if(appId==null){
			appId=APP_ID;
		}
		mFacebook=new Facebook(appId);
		mAsyncRunner=new AsyncFacebookRunner(mFacebook);
		
		this.restoreSession(mFacebook);
	}
	
	public static void init(Context context,String appId){
		if(instance==null){
			instance=new FacebookManager(context,appId);
		}
	}
	
	public static FacebookManager getInstance(){
		return instance;
	}

	public boolean isCheckNetwork() {
		return isCheckNetwork;
	}

	public void setCheckNetwork(boolean isCheckNetwork) {
		this.isCheckNetwork = isCheckNetwork;
	}

	public boolean isUseCustomProgressDialog() {
		return isUseCustomProgressDialog;
	}

	public void setUseCustomProgressDialog(boolean isUseCustomProgressDialog) {
		this.isUseCustomProgressDialog = isUseCustomProgressDialog;
	}

	public void setHandler(Handler handler){
		this.handler=handler;
	}
	
	public Handler getHandler(){
		return this.handler;
	}
	
	private void sendHandlerMsg(int what){
		if(handler!=null){
			handler.sendEmptyMessage(what);
		}
		sendBroadcast(what);
	}
	
	private void sendBroadcast(int what){
		Intent intent=new Intent();
		intent.setAction(BROADCAST_ACTION);
		intent.putExtra(BROADCAST_EXTRA_NAME, what);
		mContext.sendBroadcast(intent);
	}
	
	/**
	 * 
	 * @param context
	 * @return true if online, otherwise false.
	 */
	private boolean checkNetworkAndPrompt(Context context) {
		if(!isCheckNetwork){
			return true;
		}
		return checkNetworkAndPromptIfOffline(context);
	}
	
	public static boolean checkNetworkAndPromptIfOffline(Context context) {
		boolean isOnline = isOnline(context);
		if (isOnline) {
			return true;
		}

		AlertDialog.Builder dialog = new AlertDialog.Builder(context);
		dialog.setTitle(resIdOfflineDialogTitle)
				.setMessage(resIdOfflineDialogMessage)
				.setCancelable(false)
				.setPositiveButton(resIdButtonOk,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog, int id) {
								dialog.cancel();
							}
						});
		dialog.show();
		return false;
	}
	
	private static boolean isOnline(Context context) {
	    ConnectivityManager cm =
	        (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
	    NetworkInfo netInfo = cm.getActiveNetworkInfo();
//	    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
//	        return true;
//	    }
	    if (netInfo != null && netInfo.isConnected()) {
	        return true;
	    }
	    return false;
	}
	
	public void login(Activity activity){
		this.login(activity, true);
	}
	
	/**
	 * Display a web view for user input account and login.
	 * There is no effect if user have login before. 
	 * 
	 * @param activity 该activity需要处理onActivityResult()，
	 * 应该要调用authorizeCallback().
	 * @param requestUserData 
	 * Set true to request user data after login success.
	 * Otherwise, no user information can be saved after login, 
	 * if you want those information, should call "requestUserData()" 
	 * after login success.
	 */
	public void login(Activity activity,boolean requestUserData){
		if(mFacebook.isSessionValid()){
			return;
		}
		else{
			if(!checkNetworkAndPrompt(activity)){
				return;
			}
			
			sendHandlerMsg(MSG_LOGIN_BEGIN);
			this.requestUserData=requestUserData;
			
//			mFacebook.authorize(activity, PERMISSIONS, new LoginDialogListener());
			
			//pass -1 (the number less than 0) to prevent starting native facebook application. Only allow web view. 
			mFacebook.authorize(activity, PERMISSIONS, -1, new LoginDialogListener());
		}
	}

	public void logout() {
		sendHandlerMsg(MSG_LOGOUT_BEGIN);
//		AsyncFacebookRunner asyncRunner = new AsyncFacebookRunner(mFb);
		mAsyncRunner.logout(mContext, new LogoutRequestListener());
	}
	
	public boolean isLogin(){
		return mFacebook.isSessionValid();
	}
	
	public void authorizeCallback(int requestCode, int resultCode, Intent data){
		mFacebook.authorizeCallback(requestCode, resultCode, data);
	}
	
	public void requestUserData(){
		sendHandlerMsg(MSG_REQUEST_USER_BEGIN);
		Bundle params=new Bundle();
		params.putString("fields", "name");
		mAsyncRunner.request("me", params,new UserDataRequestListener());
	}
	
	public void requestUserStatus() {
		sendHandlerMsg(MSG_REQUEST_USER_STATUS_BEGIN);
		Bundle params = new Bundle();
		params.putString("fields", "message");
		mAsyncRunner.request("me/statuses", params, new UserStatusRequestListener());
	}
	
	/**
	 * 獲取用戶的好友列表
	 * @author Tim at 2012.11.06
	 */
	public void requestUserFriends() {
		sendHandlerMsg(MSG_REQUEST_USER_FRIENDS_BEGIN);
		Bundle params=new Bundle();
//		params.putString("fields", "id");
//		params.putString("fields", "name");
		params.putString("fields", "id, name, picture");
		mAsyncRunner.request("me/friends", params, new UserFriendsRequestListener());
	}

	public boolean isGiveUpToGetUserInfo(){
		return countRequestUserData>LIMIT_RETRY_USER_DATA;
	}
	
	private void resetRetryCountOfUserData(){
		countRequestUserData=0;
	}
	
	private void retryRequestUserData(){
		if(countRequestUserData>LIMIT_RETRY_USER_DATA){
			Log.e(TAG, "retryRequestUserData>>>countRequestUserData="+countRequestUserData);
			if(requestUserData && isLogin()){
				logout();
				// DIALOG fail to get user info.
				tipHandler.sendEmptyMessage(MSG_DIALOG_REQUEST_USER_INFO_LOST);
				//send broadcast
				sendHandlerMsg(MSG_REQUEST_USER_LOST);
			}
			return;
		}
		countRequestUserData++;
		if(isLogin()){
        	requestUserData();
        }
	}
	
	/**
	 * 
	 * @return The user's full name on Facebook. 
	 *  Maybe null if no user information is fetched from network.
	 */
	public String getUserName(){
		return username;
	}
	
	/**
	 * 
	 * @return The user's Facebook ID. 
	 *  Maybe null if no user information is fetched from network.
	 */
	public String getUserId(){
		return userId;
	}
	
	/**
	 * 
	 * @return The user's latest status.
	 */
	public String getUserStatus() {
		return userStatus;
	}
	
	public boolean isUserInfoReady(){
		return userId!=null && username!=null;
	}
	
	/*public void sharePhoto(String photoLink){
		sharePhoto(photoLink,"Android Testing.");
	}
	public void sharePhoto(String photoLink,String message){
		Bundle params = new Bundle();
		params.putString("message", message);
		params.putString("link", photoLink);
		mAsyncRunner.request("me/feed", params, "POST", new PostPhotoRequestListener(), null);
	}*/
	
	public List<Friend> getUserFriends() {
		return mFriendList;
	}
	
	public void postLink(String link){
		Bundle params = new Bundle();
		params.putString("link", link);
		mAsyncRunner.request("me/feed", params, "POST", new PostLinkRequestListener(), null);
	}
	
	public void postLinkOrLogin(Activity activity, String link){
		if(this.isLogin()){
			this.postLink(link);
		}
		else{
			this.login(activity, true);
		}
	}
	
	
	/**
	 * 
	 * @param context The context of current activity. If you pass the context of application, will occur exception.
	 * @param photoLink
	 */
	public void sharePhotoWithDialog(Context context,String photoLink){
		Bundle params = new Bundle();
		params.putString("link", photoLink);
		mFacebook.dialog(context, "feed", params,new SharePhotoDialogListener());
	}
	
	public void shareLinkWithDialog(Context context,String link){
		Bundle params = new Bundle();
		params.putString("link", link);
		mFacebook.dialog(context, "feed", params,new ShareLinkDialogListener());
	}
	
	public void sharePhotoWithDialogOrLogin(Activity activity,String photoLink){
		if(this.isLogin()){
			this.sharePhotoWithDialog(activity, photoLink);
		}
		else{
			this.login(activity, true);
		}
	}
	
	public void shareLinkWithDialogOrLogin(Activity activity,String link){
		if(this.isLogin()){
			this.shareLinkWithDialog(activity, link);
		}
		else{
			this.login(activity, true);
		}
	}
	
	private FbConnection currentFbConnection=null;
	public synchronized void shareAction(String link,String picture,String name,
			String caption,String description,String message){
		Bundle parameters=new Bundle();
		parameters.putString("app_id", mFacebook.getAppId());
		parameters.putString("link", link);
		parameters.putString("picture", picture);
		parameters.putString("name", name);
		parameters.putString("caption", caption);
		parameters.putString("description", description);
		parameters.putString("message", message);
		
		//"me/feed"与"feed"有不同。在facebook的wall显示caption时，前者显示link，后者正常显示caption。而timeline显示两都正常，fb有bug.
		currentFbConnection=mAsyncRunner.requestFbConnection("feed", parameters, 
				"POST" , new ShareActionRequestListener(), this);
	}
	
	public void shareActionWithDialog(Context context,String link,
			String picture,String name,
			String caption,String description){
		if(!checkNetworkAndPrompt(context)){
			return;
		}
		
		Bundle parameters=new Bundle();
		parameters.putString("app_id", mFacebook.getAppId());
		parameters.putString("link", link);
		parameters.putString("picture", picture);
		parameters.putString("name", name);
		parameters.putString("caption", caption);
		parameters.putString("description", description);
		mFacebook.dialog(context, "feed", parameters, new ShareActionDialogListener());
	}
	
	public synchronized void closeCurrentConnection(){
//		Util.closeCurrentConnection();
		if(currentFbConnection!=null){
			currentFbConnection.forceClose();
			currentFbConnection=null;
		}
	}
	
//	public void uploadPhoto(){//server handle.
//		
//	}
	
	public String getLastLoginErrorMessage(){
		return this.lastLoginErrorMessage;
	}
	
	//{内部类
	private abstract class BaseRequestListener implements RequestListener {

	    @Override
	    public void onFacebookError(FacebookError e, final Object state) {
	        
	        e.printStackTrace();
	    }

	    @Override
	    public void onFileNotFoundException(FileNotFoundException e, final Object state) {
	        
	        e.printStackTrace();
	    }

	    @Override
	    public void onIOException(IOException e, final Object state) {
	        
	        e.printStackTrace();
	    }

	    @Override
	    public void onMalformedURLException(MalformedURLException e, final Object state) {
	        
	        e.printStackTrace();
	    }

		@Override
		public void onForceCloseIOException(ForceCloseIOException e) {
			
		}
	}
	
	private abstract class BaseDialogListener implements DialogListener {

		@Override
		public void onFacebookError(FacebookError e) {
			Log.e(TAG, "BaseDialogListener>>>onFacebookError="+e.toString());
		}

		@Override
		public void onError(DialogError e) {
			Log.e(TAG, "BaseDialogListener>>>onError="+e.toString());
		}

		@Override
		public void onCancel() {
			Log.e(TAG, "BaseDialogListener>>>onCancel");
		}
		
		public void onProgressDialogCancel() {
			if(handler != null) {
				handler.sendEmptyMessage(MSG_PROGRESS_DIALOG_ON_CANCLEL);
			}
		}
	}

	
	private final class LoginDialogListener implements DialogListener {
        public void onComplete(Bundle values) {
        	Log.e(TAG, "LoginDialogListener>>>onComplete");
//        	Set<String> keySet=values.keySet();
//        	if(keySet!=null){
//        		for(String key:keySet){
////        			这行会有exception Log.e(TAG, "LoginDialogListener>>>onComplete>>>"+key+"="+values.getByte(key));
//        			Log.e(TAG, "LoginDialogListener>>>onComplete>>>key="+key);
//        		}
//        	}
//        	else{
//        		Log.e(TAG, "LoginDialogListener>>>onComplete>>>keySet is null");
//        	}
        	
        	resetRetryCountOfUserData();
            saveSession(mFacebook);
            if(requestUserData && isLogin()){
            	requestUserData();
//            	requestUserStatus();	不需要在登錄後馬上獲取用戶的status，請手動在外部調用requestUserStatus()，並接收廣播.
            }
            
            sendHandlerMsg(MSG_LOGIN_END);
        }

        public void onFacebookError(FacebookError error) {
        	lastLoginErrorMessage=error.getMessage();
        	Log.e(TAG, "LoginDialogListener>>>onFacebookError="+lastLoginErrorMessage);
        	sendHandlerMsg(MSG_LOGIN_ERROR);
        }
        
        public void onError(DialogError error) {
        	lastLoginErrorMessage=error.getMessage();
        	Log.e(TAG, "LoginDialogListener>>>onError="+lastLoginErrorMessage);
        	sendHandlerMsg(MSG_LOGIN_ERROR);
        }

        public void onCancel() {
        	Log.e(TAG, "LoginDialogListener>>>onCancel");
        	sendHandlerMsg(MSG_LOGIN_CANCEL);
        }
        
        public void onTimeout(){
        	sendHandlerMsg(MSG_LOGIN_TIMEOUT);
        }
        
        public void onProgressDialogCancel() {
        	sendHandlerMsg(MSG_PROGRESS_DIALOG_ON_CANCLEL);
        }
    }
	
	
	private class LogoutRequestListener extends BaseRequestListener{
		@Override
		public void onComplete(String response, Object state) {
			 Log.e(TAG, "LogoutRequestListener onComplete>>>");
			userId=null;
			username=null;
			userStatus = null;
			clearSession();
			sendHandlerMsg(MSG_LOGOUT_END);
		}
		
		@Override
	    public void onIOException(IOException e, final Object state) {
	        Log.e(TAG, "onIOException>>>"+e.getMessage());
	        e.printStackTrace();
//	        sendHandlerMsg(MSG_LOGOUT_IO_ERROR);
	        
	        //{20120719
	        //Login success with GT_V, switch GT_3(Can't access facebook website), can NOT logout and IOException. 
	        //Switch back to GT_V, still not success. Must restart application, then logout is OK.
	        //Preventing such problem, I force the data of facebook removed from storage.
	        userId=null;
			username=null;
			userStatus = null;
			clearSession();
			mFacebook.setAccessToken(null);
			mFacebook.setAccessExpires(0);
			sendHandlerMsg(MSG_LOGOUT_END);
			//}
	    }
	}
	
	private class UserDataRequestListener extends BaseRequestListener {

		@Override
		public void onFacebookError(FacebookError e, final Object state) {
			
			e.printStackTrace();
			retryRequestUserData();
		}

		@Override
		public void onIOException(IOException e, final Object state) {
			
			e.printStackTrace();
			retryRequestUserData();
		}

        @Override
        public void onComplete(final String response, final Object state) {
            JSONObject jsonObject;
            try {
            	Log.i(TAG, "UserDataRequestListener>>>response="+response);
                jsonObject = new JSONObject(response);

                username = jsonObject.getString("name");
                userId = jsonObject.getString("id");
                
                saveUsername(username);
                saveUserId(userId);

                sendHandlerMsg(MSG_REQUEST_USER_END);
            } catch (Exception e) {
                e.printStackTrace();
                retryRequestUserData();
            }
        }

    }
	
	private class UserStatusRequestListener extends BaseRequestListener {

		@Override
		public void onFacebookError(FacebookError e, final Object state) {
			e.printStackTrace();
			sendHandlerMsg(MSG_REQUEST_USER_STATUS_ERROR);
		}

		@Override
		public void onIOException(IOException e, final Object state) {
			e.printStackTrace();
			sendHandlerMsg(MSG_REQUEST_USER_STATUS_ERROR);
		}
		
		@Override
		public void onComplete(String response, Object state) {
			JSONObject jObject = null;
			try {
				Log.i(TAG, "UserStatusRequestListener >>> response="+response);
				jObject = new JSONObject(response).getJSONArray("data").getJSONObject(0);
				userStatus = jObject.getString("message");
				sendHandlerMsg(MSG_REQUEST_USER_STATUS_END);
			} catch(Exception e) {
				e.printStackTrace();
				sendHandlerMsg(MSG_REQUEST_USER_STATUS_ERROR);
			}
		}
		
	}
	
	private class UserFriendsRequestListener extends BaseRequestListener {

		@Override
		public void onFacebookError(FacebookError e, final Object state) {
			e.printStackTrace();
			sendHandlerMsg(MSG_REQUEST_USER_FRIENDS_ERROR);
		}

		@Override
		public void onIOException(IOException e, final Object state) {
			
			e.printStackTrace();
			sendHandlerMsg(MSG_REQUEST_USER_FRIENDS_ERROR);
		}
		
		@Override
		public void onComplete(String response, Object state) {
			try {
				Log.i(TAG, "UserFriendsRequestListener >>> response="+response);
				synchronized (mFriendList) {
					mFriendList.clear();
					JSONArray jArray = new JSONObject(response).getJSONArray("data");
					int length = jArray.length();
					for(int i = 0; i < length; i++) {
						JSONObject jObject = jArray.getJSONObject(i);
						Friend aFriend = new Friend(jObject);
						mFriendList.add(aFriend);
					}
				}
				sendHandlerMsg(MSG_REQUEST_USER_FRIENDS_END);
			} catch(Exception e) {
				e.printStackTrace();
				sendHandlerMsg(MSG_REQUEST_USER_FRIENDS_ERROR);
			}
		}
		
	}
	
	private class PostPhotoRequestListener extends BaseRequestListener{

		@Override
		public void onComplete(String response, Object state) {
			Log.i(TAG, "PostPhotoRequestListener>>>response="+response);
			
			sendHandlerMsg(MSG_SHARE_PHOTO_END);
		}
		
	}
	
	private class ShareActionRequestListener extends BaseRequestListener{

		@Override
		public void onFacebookError(FacebookError e, final Object state) {
			
			e.printStackTrace();
			sendHandlerMsg(MSG_SHARE_ACTION_FB_ERROR);
		}

		@Override
		public void onIOException(IOException e, final Object state) {
			
			e.printStackTrace();
			sendHandlerMsg(MSG_SHARE_ACTION_IO_ERROR);
		}
	    
		@Override
		public void onComplete(String response, Object state) {
			Log.i(TAG, "ShareActionRequestListener>>>response="+response);
			//TODO should analyse the data "response".
			sendHandlerMsg(MSG_SHARE_ACTION_END);
		}
		
	}
	
	private class SharePhotoDialogListener extends BaseDialogListener{

		@Override
		public void onFacebookError(FacebookError e) {
			Log.e(TAG, "SharePhotoDialogListener>>>onFacebookError="+e.toString());
			sendHandlerMsg(MSG_SHARE_PHOTO_FB_ERROR);
		}

		@Override
		public void onError(DialogError e) {
			Log.e(TAG, "SharePhotoDialogListener>>>onError="+e.toString());
			sendHandlerMsg(MSG_SHARE_PHOTO_IO_ERROR);
		}

		@Override
		public void onCancel() {
			Log.e(TAG, "SharePhotoDialogListener>>>onCancel");
			sendHandlerMsg(MSG_SHARE_PHOTO_CANCEL);
		}
		@Override
		public void onComplete(Bundle values) {
			Log.e(TAG, "SharePhotoDialogListener>>>onComplete");
			sendHandlerMsg(MSG_SHARE_PHOTO_END);
		}
		
		public void onTimeout(){
        	sendHandlerMsg(MSG_SHARE_PHOTO_TIMEOUT);
        }
		
	}
	
	private class PostLinkRequestListener extends BaseRequestListener {

		@Override
		public void onFacebookError(FacebookError e, final Object state) {
			
			e.printStackTrace();
			sendHandlerMsg(MSG_POST_LINK_FB_ERROR);
		}

		@Override
		public void onIOException(IOException e, final Object state) {
			
			e.printStackTrace();
			sendHandlerMsg(MSG_POST_LINK_IO_ERROR);
		}

		@Override
		public void onComplete(String response, Object state) {
			Log.i(TAG, "PostLinkRequestListener>>>response=" + response);

			sendHandlerMsg(MSG_POST_LINK_END);
		}

	}
	
	private class ShareLinkDialogListener extends BaseDialogListener{

		@Override
		public void onFacebookError(FacebookError e) {
			Log.e(TAG, "ShareLinkDialogListener>>>onFacebookError="+e.toString());
			sendHandlerMsg(MSG_SHARE_LINK_FB_ERROR);
		}

		@Override
		public void onError(DialogError e) {
			Log.e(TAG, "ShareLinkDialogListener>>>onError="+e.toString());
			sendHandlerMsg(MSG_SHARE_LINK_ERROR);
		}

		@Override
		public void onCancel() {
			Log.e(TAG, "ShareLinkDialogListener>>>onCancel");
			sendHandlerMsg(MSG_SHARE_LINK_CANCEL);
		}
		
		@Override
		public void onComplete(Bundle values) {
			Log.e(TAG, "ShareLinkDialogListener>>>onComplete");
			sendHandlerMsg(MSG_SHARE_LINK_END);
		}
		
		public void onTimeout(){
        	sendHandlerMsg(MSG_SHARE_LINK_TIMEOUT);
        }
	}
	
	private class ShareActionDialogListener extends BaseDialogListener{

		@Override
		public void onFacebookError(FacebookError e) {
			Log.e(TAG, "ShareActionDialogListener>>>onFacebookError="+e.toString());
			sendHandlerMsg(MSG_SHARE_ACTION_FB_ERROR);
		}

		@Override
		public void onError(DialogError e) {
			Log.e(TAG, "ShareActionDialogListener>>>onError="+e.toString());
			sendHandlerMsg(MSG_SHARE_ACTION_ERROR);
		}

		@Override
		public void onCancel() {
			Log.e(TAG, "ShareActionDialogListener>>>onCancel");
			sendHandlerMsg(MSG_SHARE_ACTION_CANCEL);
		}
		
		@Override
		public void onComplete(Bundle values) {
			Log.e(TAG, "ShareActionDialogListener>>>onComplete");
			sendHandlerMsg(MSG_SHARE_ACTION_END);
		}
		
		public void onTimeout(){
        	sendHandlerMsg(MSG_SHARE_ACTION_TIMEOUT);
        }
	}
	//}
	
	
	private boolean saveSession(Facebook fb){
		Editor editor=mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE).edit();
		editor.putString(KEY_ACCESS_TOKEN, fb.getAccessToken());
		editor.putLong(KEY_ACCESS_EXPIRES, fb.getAccessExpires());
		Log.i(TAG, "saveSession>>>"+fb.getAccessToken()+";"+fb.getAccessExpires());
		return editor.commit();
	}
	
	private boolean saveUsername(String username){
		if(username!=null){
			Editor editor=mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE).edit();
			editor.putString(KEY_USERNAME, username);
			return editor.commit();
		}
		return false;
	}
	
	private boolean saveUserId(String userId){
		if(userId!=null){
			Editor editor=mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE).edit();
			editor.putString(KEY_USERID, userId);
			return editor.commit();
		}
		return false;
	}
	
	private boolean saveUserStatus(String status) {
		if(status != null) {
			Editor editor=mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE).edit();
			editor.putString(KEY_USER_STATUS, status);
			return editor.commit();
		}
		return false;
	}
	
	private boolean restoreSession(Facebook fb){
		SharedPreferences spf=mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE);
		String accessToken=spf.getString(KEY_ACCESS_TOKEN, null);
		long accessExpires=spf.getLong(KEY_ACCESS_EXPIRES, 0);
		if(accessToken!=null && accessExpires!=0){
			fb.setAccessToken(accessToken);
			fb.setAccessExpires(accessExpires);
			this.username=spf.getString(KEY_USERNAME, null);
			this.userId=spf.getString(KEY_USERID, null);
		}
		return fb.isSessionValid();
	}
	
	private void clearSession(){
		mContext.getSharedPreferences(SHAREPREF_NAME, Context.MODE_PRIVATE).edit().clear().commit();
	}
	
	public static void setResIdTextLoading(int resId){
	    FbDialog.setResIdTextLoading(resId);
	}
	
	public static void setResIdTextNoUserInfo(int resId){
		resIdTextNoUserInfo=resId;
	}
	
	public static void setResIdTextButtonOk(int resId){
		resIdButtonOk=resId;
	}
	
	
	public static int getResIdOfflineDialogTitle() {
		return resIdOfflineDialogTitle;
	}

	public static void setResIdOfflineDialogTitle(int resIdOfflineDialogTitle) {
		FacebookManager.resIdOfflineDialogTitle = resIdOfflineDialogTitle;
	}

	public static int getResIdOfflineDialogMessage() {
		return resIdOfflineDialogMessage;
	}

	public static void setResIdOfflineDialogMessage(int resIdOfflineDialogMessage) {
		FacebookManager.resIdOfflineDialogMessage = resIdOfflineDialogMessage;
	}

	public String getLastLoginUrl(){
    	return mFacebook.getLastLoginUrl();
    }
	
	public String getFacebookAccessToken(){
		if(mFacebook!=null){
			return mFacebook.getAccessToken();
		}
		return null;
	}

	private static final int MSG_DIALOG_REQUEST_USER_INFO_LOST=509;
	private Handler tipHandler=new Handler(){	
		public void handleMessage(Message msg){
			switch(msg.what){
			case MSG_DIALOG_REQUEST_USER_INFO_LOST:
				CharSequence messageBody=mContext.getResources().getText(resIdTextNoUserInfo,
						"Network error. Please login your Facebook again.");
//				CharSequence buttonOk=mContext.getResources().getText(resIdButtonOk, "OK");
//				new AlertDialog.Builder(mContext).setCancelable(true)
//					.setTitle(null).setMessage(messageBody)
//					.setPositiveButton(buttonOk, null).create().show();
				Toast.makeText(mContext, messageBody, Toast.LENGTH_SHORT).show();
				break;
			}
		}
	};
	
	public void setTypeface(Typeface tf) {
		if(mFacebook != null) {
			mFacebook.setTypeface(tf);
		}
	}
}
